home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / lisp / stk-3.002 / stk-3 / STk-3.1 / Tk / unix / tkUnixEvent.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-31  |  5.1 KB  |  195 lines

  1. /* 
  2.  * tkUnixEvent.c --
  3.  *
  4.  *    This file implements an event source for X displays for the
  5.  *    UNIX version of Tk.
  6.  *
  7.  * Copyright (c) 1995 Sun Microsystems, Inc.
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  *
  12.  * SCCS: @(#) tkUnixEvent.c 1.5 96/02/15 18:55:30
  13.  */
  14.  
  15. #include "tkInt.h"
  16. #include "tkUnixInt.h"
  17. #include <signal.h>
  18.  
  19. /*
  20.  * Prototypes for procedures that are referenced only in this file:
  21.  */
  22.  
  23. static void        DisplayCheckProc _ANSI_ARGS_((ClientData clientData,
  24.                 int flags));
  25. static void        DisplaySetupProc _ANSI_ARGS_((ClientData clientData,
  26.                 int flags));
  27.  
  28. /*
  29.  *----------------------------------------------------------------------
  30.  *
  31.  * DisplaySetupProc --
  32.  *
  33.  *    This procedure is part of the event source for UNIX X displays.
  34.  *    It is invoked by Tcl_DoOneEvent before it calls select to check
  35.  *    for events on all displays.
  36.  *
  37.  * Results:
  38.  *    None.
  39.  *
  40.  * Side effects:
  41.  *    Tells the notifier which files should be waited for.
  42.  *
  43.  *----------------------------------------------------------------------
  44.  */
  45.  
  46. static void
  47. DisplaySetupProc(clientData, flags)
  48.     ClientData clientData;        /* Not used. */
  49.     int flags;                /* Flags passed to Tk_DoOneEvent:
  50.                      * if it doesn't include
  51.                      * TCL_WINDOW_EVENTS then we do
  52.                      * nothing. */
  53. {
  54.     TkDisplay *dispPtr;
  55.     static Tcl_Time dontBlock = {0, 0};
  56.  
  57.     if (!(flags & TCL_WINDOW_EVENTS)) {
  58.     return;
  59.     }
  60.  
  61.     for (dispPtr = tkDisplayList; dispPtr != NULL; dispPtr = dispPtr->nextPtr) {
  62.     Tcl_File handle;
  63.     XFlush(dispPtr->display);
  64.     if (XQLength(dispPtr->display) > 0) {
  65.         Tcl_SetMaxBlockTime(&dontBlock);
  66.     }
  67.     handle = Tcl_GetFile(
  68.         (ClientData)ConnectionNumber(dispPtr->display), TCL_UNIX_FD);
  69.     Tcl_WatchFile(handle, TCL_READABLE);
  70.     }
  71. }
  72.  
  73. /*
  74.  *----------------------------------------------------------------------
  75.  *
  76.  * DisplayCheckProc --
  77.  *
  78.  *    This procedure is the second part of the "event source" for
  79.  *    X displays.  It is invoked by Tcl_DoOneEvent after it calls
  80.  *    select (or whatever it uses to wait for events).
  81.  *
  82.  * Results:
  83.  *    None.
  84.  *
  85.  * Side effects:
  86.  *    Makes entries on the Tcl event queue for all the events available
  87.  *    from all the displays.
  88.  *
  89.  *----------------------------------------------------------------------
  90.  */
  91.  
  92. static void
  93. DisplayCheckProc(clientData, flags)
  94.     ClientData clientData;        /* Not used. */
  95.     int flags;                /* Flags passed to Tk_DoOneEvent:
  96.                      * if it doesn't include 
  97.                      * TCL_WINDOW_EVENTS then we do
  98.                      * nothing. */
  99. {
  100.     TkDisplay *dispPtr;
  101.     XEvent event;
  102.     int numFound;
  103.  
  104.     if (!(flags & TCL_WINDOW_EVENTS)) {
  105.     return;
  106.     }
  107.  
  108.     for (dispPtr = tkDisplayList; dispPtr != NULL; dispPtr = dispPtr->nextPtr) {
  109.     Tcl_File handle;
  110.     /*
  111.      * Note: we should not need to do a flush of the output queues before
  112.      * calling XEventsQueued because it was done by DisplaySetupProc.
  113.      */
  114.  
  115.     handle = Tcl_GetFile(
  116.         (ClientData) ConnectionNumber(dispPtr->display), TCL_UNIX_FD);
  117.     if (Tcl_FileReady(handle, TCL_READABLE) != 0) {
  118.         numFound = XEventsQueued(dispPtr->display, QueuedAfterReading);
  119.         if (numFound == 0) {
  120.     
  121.         /*
  122.          * Things are very tricky if there aren't any events readable
  123.          * at this point (after all, there was supposedly data
  124.          * available on the connection).  A couple of things could
  125.          * have occurred:
  126.          * 
  127.          * One possibility is that there were only error events in the
  128.          * input from the server.  If this happens, we should return
  129.          * (we don't want to go to sleep in XNextEvent below, since
  130.          * this would block out other sources of input to the
  131.          * process).
  132.          *
  133.          * Another possibility is that our connection to the server
  134.          * has been closed.  This will not necessarily be detected in
  135.          * XEventsQueued (!!), so if we just return then there will be
  136.          * an infinite loop.  To detect such an error, generate a NoOp
  137.          * protocol request to exercise the connection to the server,
  138.          * then return.  However, must disable SIGPIPE while sending
  139.          * the request, or else the process will die from the signal
  140.          * and won't invoke the X error function to print a nice (?!)
  141.          * message.
  142.          */
  143.     
  144.         void (*oldHandler)();
  145.     
  146.         oldHandler = (void (*)()) signal(SIGPIPE, SIG_IGN);
  147.         XNoOp(dispPtr->display);
  148.         XFlush(dispPtr->display);
  149.         (void) signal(SIGPIPE, oldHandler);
  150.         }
  151.     } else {
  152.         numFound = XQLength(dispPtr->display);
  153.     }
  154.     
  155.     /*
  156.      * Transfer events from the X event queue to the Tk event queue.
  157.      */
  158.  
  159.     while (numFound > 0) {
  160.         XNextEvent(dispPtr->display, &event);
  161.         Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
  162.         numFound--;
  163.     }
  164.     }
  165. }
  166.  
  167. /*
  168.  *----------------------------------------------------------------------
  169.  *
  170.  * TkCreateXEventSource --
  171.  *
  172.  *    This procedure is called during Tk initialization to create
  173.  *    the event source for X Window events.
  174.  *
  175.  * Results:
  176.  *    None.
  177.  *
  178.  * Side effects:
  179.  *    A new event source is created.
  180.  *
  181.  *----------------------------------------------------------------------
  182.  */
  183.  
  184. void
  185. TkCreateXEventSource()
  186. {
  187.     static int initialized = 0;
  188.  
  189.     if (!initialized) {
  190.     Tcl_CreateEventSource(DisplaySetupProc, DisplayCheckProc,
  191.         (ClientData) NULL);
  192.     initialized = 1;
  193.     }
  194. }
  195.